package com.yarolegovich.lovelydialog;

import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.utils.PacMap;

/**
 * Created by yarolegovich on 16.04.2016.
 */
public class LovelyTextInputDialog extends AbsLovelyDialog<LovelyTextInputDialog> {
    private static final String KEY_HAS_ERROR = "key_has_error";
    private static final String KEY_TYPED_TEXT = "key_typed_text";
    private TextField inputField;
    private Text errorMessage;
    private Text confirmButton;
    private Text negativeButton;
    private TextFilter filter;

    public LovelyTextInputDialog(Context context) {
        super(context);
    }

    public LovelyTextInputDialog(Context context, int theme) {
        super(context, theme);
    }

    {
        confirmButton = findView(ResourceTable.Id_btn_confirm);
        negativeButton = findView(ResourceTable.Id_btn_negative);
        inputField = findView(ResourceTable.Id_text_input);
        errorMessage = findView(ResourceTable.Id_error_message);
        inputField.addTextObserver(new HideErrorOnTextChanged());
    }

    public LovelyTextInputDialog configureEditText(ViewConfigurator<TextField> viewConfigurator) {
        viewConfigurator.configureView(inputField);
        return this;
    }

    public LovelyTextInputDialog setConfirmButton(int text, OnTextInputConfirmListener listener) {
        return setConfirmButton(string(text), listener);
    }

    public LovelyTextInputDialog setConfirmButton(String text, OnTextInputConfirmListener listener) {
        confirmButton.setText(text);
        confirmButton.setClickedListener(new TextInputListener(listener));
        return this;
    }

    public LovelyTextInputDialog setConfirmButtonColor(int color) {
        confirmButton.setTextColor(new Color(color));
        return this;
    }

    public LovelyTextInputDialog setNegativeButton(int text, Component.ClickedListener listener) {
        return setNegativeButton(string(text), listener);
    }

    public LovelyTextInputDialog setNegativeButton(String text, Component.ClickedListener listener) {
        negativeButton.setVisibility(Component.VISIBLE);
        negativeButton.setText(text);
        negativeButton.setClickedListener(new ClickListenerDecorator(listener, true));
        return this;
    }

    public LovelyTextInputDialog setNegativeButtonColor(int color) {
        negativeButton.setTextColor(new Color(color));
        return this;
    }

    public LovelyTextInputDialog setInputFilter(int errorMessage, TextFilter filter) {
        return setInputFilter(string(errorMessage), filter);
    }

    public LovelyTextInputDialog setInputFilter(String errorMessage, TextFilter filter) {
        this.filter = filter;
        this.errorMessage.setText(errorMessage);
        return this;
    }

    public LovelyTextInputDialog setErrorMessageColor(int color) {
        errorMessage.setTextColor(new Color(color));
        return this;
    }

    public LovelyTextInputDialog setInputType(int inputType) {
        inputField.setInputMethodOption(inputType);
        return this;
    }

    public LovelyTextInputDialog addTextWatcher(Text.TextObserver textWatcher) {
        inputField.addTextObserver(textWatcher);
        return this;
    }

    public LovelyTextInputDialog setInitialInput(int text) {
        return setInitialInput(string(text));
    }

    public LovelyTextInputDialog setInitialInput(String text) {
        inputField.setText(text);
        return this;
    }

    public LovelyTextInputDialog setHint(int hint) {
        return setHint(string(hint));
    }

    public LovelyTextInputDialog setHint(String text) {
        inputField.setHint(text);
        return this;
    }

    private void setError() {
        errorMessage.setVisibility(Component.VISIBLE);
    }

    private void hideError() {
        errorMessage.setVisibility(Component.HIDE);
    }

    @Override
    void onSaveInstanceState(PacMap outState) {
        super.onSaveInstanceState(outState);
        outState.putBooleanValue(KEY_HAS_ERROR, errorMessage.getVisibility() == Component.VISIBLE);
        outState.putString(KEY_TYPED_TEXT, inputField.getText().toString());
    }

    @Override
    void restoreState(PacMap savedState) {
        super.restoreState(savedState);
        if (savedState.getBooleanValue(KEY_HAS_ERROR, false)) {
            setError();
        }
        inputField.setText(savedState.getString(KEY_TYPED_TEXT));
    }

    @Override
    protected int getLayout() {
        return ResourceTable.Layout_dialog_text_input;
    }

    private class TextInputListener implements Component.ClickedListener {

        private OnTextInputConfirmListener wrapped;

        private TextInputListener(OnTextInputConfirmListener wrapped) {
            this.wrapped = wrapped;
        }

        @Override
        public void onClick(Component component) {
            String text = inputField.getText().toString();
            if (filter != null) {
                boolean isWrongInput = !filter.check(text);
                if (isWrongInput) {
                    setError();
                    return;
                }
            }
            if (wrapped != null) {
                wrapped.onTextInputConfirmed(text);
            }
            dismiss();
        }
    }

    private class HideErrorOnTextChanged implements Text.TextObserver {
        @Override
        public void onTextUpdated(String str, int i0, int i1, int i2) {
            hideError();
        }
    }

    public interface OnTextInputConfirmListener {
        void onTextInputConfirmed(String text);
    }

    public interface TextFilter {
        boolean check(String text);
    }
}
